package com.smart.community.property.dto;

import com.smart.community.commons.base.BaseDTO;
import lombok.Data;
import lombok.EqualsAndHashCode;

import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;

/**
 * 批量物业费操作数据传输对象
 * @author Wu.Liang
 * @since 2025-06-26
 * @version 1.0.0
 */
@Data
@EqualsAndHashCode(callSuper = true)
public class BatchPropertyFeeDTO extends BaseDTO {
    private static final long serialVersionUID = 4566722793198499605L;

	/**
     * 社区ID
     */
    @NotNull(message = "社区ID不能为空")
    private Long communityId;
    
    /**
     * 费用类型：1-物业费，2-水费，3-电费，4-燃气费，5-卫生费
     */
    @NotNull(message = "费用类型不能为空")
    @Min(value = 1, message = "费用类型值无效")
    @Max(value = 5, message = "费用类型值无效")
    private Integer feeType;
    
    /**
     * 费用名称
     */
    @NotBlank(message = "费用名称不能为空")
    @Size(max = 50, message = "费用名称长度不能超过50个字符")
    private String feeName;
    
    /**
     * 计费周期
     */
    @NotBlank(message = "计费周期不能为空")
    @Size(max = 20, message = "计费周期长度不能超过20个字符")
    private String billingPeriod;
    
    /**
     * 缴费截止日期
     */
    @NotNull(message = "缴费截止日期不能为空")
    private LocalDate dueDate;
    
    /**
     * 批量生成模式：1-按房屋面积，2-按固定金额，3-按阶梯收费
     */
    @NotNull(message = "批量生成模式不能为空")
    @Min(value = 1, message = "批量生成模式值无效")
    @Max(value = 3, message = "批量生成模式值无效")
    private Integer batchMode;
    
    /**
     * 单价（批量生成模式为1时使用）
     */
    @DecimalMin(value = "0.01", message = "单价必须大于0")
    @Digits(integer = 10, fraction = 2, message = "单价格式不正确")
    private BigDecimal unitPrice;
    
    /**
     * 固定金额（批量生成模式为2时使用）
     */
    @DecimalMin(value = "0.01", message = "固定金额必须大于0")
    @Digits(integer = 10, fraction = 2, message = "固定金额格式不正确")
    private BigDecimal fixedAmount;
    
    /**
     * 阶梯收费规则（批量生成模式为3时使用）
     */
    private List<LadderRule> ladderRules;
    
    /**
     * 房屋ID列表（为空时生成所有房屋）
     */
    private List<Long> householdIds;
    
    /**
     * 排除的房屋ID列表
     */
    private List<Long> excludeHouseholdIds;
    
    /**
     * 备注
     */
    @Size(max = 500, message = "备注长度不能超过500个字符")
    private String remark;
    
    /**
     * 阶梯收费规则内部类
     */
    @Data
    public static class LadderRule {
        
        /**
         * 最小用量
         */
        @DecimalMin(value = "0.00", message = "最小用量不能为负数")
        @Digits(integer = 10, fraction = 2, message = "最小用量格式不正确")
        private BigDecimal minUsage;
        
        /**
         * 最大用量（为空表示无上限）
         */
        @DecimalMin(value = "0.00", message = "最大用量不能为负数")
        @Digits(integer = 10, fraction = 2, message = "最大用量格式不正确")
        private BigDecimal maxUsage;
        
        /**
         * 单价
         */
        @DecimalMin(value = "0.01", message = "单价必须大于0")
        @Digits(integer = 10, fraction = 2, message = "单价格式不正确")
        @NotNull(message = "单价不能为空")
        private BigDecimal unitPrice;
        
        /**
         * 基础费用
         */
        @DecimalMin(value = "0.00", message = "基础费用不能为负数")
        @Digits(integer = 10, fraction = 2, message = "基础费用格式不正确")
        private BigDecimal baseFee = BigDecimal.ZERO;
    }
    
    /**
     * 验证批量生成参数
     * @return 验证结果
     */
    public boolean validateBatchGenerate() {
        if (batchMode == null || batchMode < 1 || batchMode > 3) {
            return false;
        }
        
        if (communityId == null || feeType == null || feeType < 1 || feeType > 5) {
            return false;
        }
        
        if (billingPeriod == null || billingPeriod.trim().isEmpty()) {
            return false;
        }
        
        if (dueDate == null) {
            return false;
        }
        
        // 根据批量生成模式验证相应参数
        switch (batchMode) {
            case 1: // 按房屋面积
                return unitPrice != null && unitPrice.compareTo(BigDecimal.ZERO) > 0;
            case 2: // 按固定金额
                return fixedAmount != null && fixedAmount.compareTo(BigDecimal.ZERO) > 0;
            case 3: // 按阶梯收费
                return ladderRules != null && !ladderRules.isEmpty();
            default:
                return false;
        }
    }
    
    /**
     * 计算阶梯费用
     * @param usage 用量
     * @return 计算出的费用
     */
    public BigDecimal calculateLadderFee(BigDecimal usage) {
        if (batchMode != 3 || ladderRules == null || ladderRules.isEmpty()) {
            return BigDecimal.ZERO;
        }
        
        BigDecimal totalFee = BigDecimal.ZERO;
        BigDecimal remainingUsage = usage;
        
        for (LadderRule rule : ladderRules) {
            if (remainingUsage.compareTo(BigDecimal.ZERO) <= 0) {
                break;
            }
            
            BigDecimal ruleUsage;
            if (rule.getMaxUsage() == null) {
                // 无上限，使用剩余用量
                ruleUsage = remainingUsage;
            } else {
                // 有上限，取较小值
                ruleUsage = remainingUsage.min(rule.getMaxUsage().subtract(rule.getMinUsage()));
            }
            
            if (ruleUsage.compareTo(BigDecimal.ZERO) <= 0) {
                continue;
            }
            
            BigDecimal ruleFee = ruleUsage.multiply(rule.getUnitPrice()).add(rule.getBaseFee());
            totalFee = totalFee.add(ruleFee);
            remainingUsage = remainingUsage.subtract(ruleUsage);
        }
        
        return totalFee;
    }
    
    /**
     * 获取批量生成模式名称
     * @return 批量生成模式名称
     */
    public String getBatchModeName() {
        if (batchMode == null) {
            return "未知";
        }
        
        switch (batchMode) {
            case 1:
                return "按房屋面积";
            case 2:
                return "按固定金额";
            case 3:
                return "按阶梯收费";
            default:
                return "未知";
        }
    }
    
    /**
     * 获取费用类型名称
     * @return 费用类型名称
     */
    public String getFeeTypeName() {
        if (feeType == null) {
            return "未知";
        }
        
        switch (feeType) {
            case 1:
                return "物业费";
            case 2:
                return "水费";
            case 3:
                return "电费";
            case 4:
                return "燃气费";
            case 5:
                return "卫生费";
            default:
                return "未知";
        }
    }
} 